package com.bobbygu.server.simpleapp.socket;

import com.bobbygu.server.simpleapp.socket.protocol.BasicProtocol;
import com.bobbygu.server.simpleapp.socket.protocol.DataProtocol;
import com.bobbygu.server.simpleapp.socket.utils.Config;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


public class ConnectionServer {
    private static boolean isStart = true;
//        private static ServerResponseTask serverResponseTask;
    private static ConcurrentHashMap<String, ServerResponseTask> tasks = new ConcurrentHashMap<>();

    public static void run() {
        ServerSocket serverSocket = null;
        ExecutorService executorService = Executors.newCachedThreadPool();
        try {
            serverSocket = new ServerSocket(Config.PORT);
        } catch (IOException e) {
            e.printStackTrace();
        }
        ServerSocket finalServerSocket = serverSocket;
        executorService.execute(() -> listen(executorService, finalServerSocket));
    }

    /**
     * 给指定客户推送消息
     *
     * @param clientID 客户id
     * @param msg      消息
     */
    public static void pushMsg(String clientID, BasicProtocol msg) {
        ServerResponseTask task = tasks.get(clientID);
        if (task != null) {
            task.addMessage(msg);
        }
    }

    /**
     * 获取客户列表
     *
     * @return 客户列表
     */
    public static ArrayList<String> getClientList() {
        ArrayList<String> result = new ArrayList<>();
        result.addAll(tasks.keySet());
        return result;
    }

    private static void listen(ExecutorService executorService, ServerSocket serverSocket) {
        try {
            while (isStart) {
                System.out.println("tasks.size():" + tasks.size());
                Socket socket = serverSocket.accept();
                String userId = socket.toString();
//                socket.setOOBInline(true);
                ServerResponseTask serverResponseTask;
                if (tasks.get(userId) == null) {
                    serverResponseTask = new ServerResponseTask(socket,
                            new ResponseCallback() {

                                @Override
                                public void targetIsOffline(DataProtocol reciveMsg) {// 对方不在线
                                    if (reciveMsg != null) {
                                        System.out.println(reciveMsg.getData());
                                    }
                                }

                                @Override
                                public void targetIsOnline(String clientIp) {
                                    System.out.println(clientIp + " is onLine");
                                    System.out.println("-----------------------------------------");
                                }
                            });
                    serverResponseTask.setOfflineListener(clientId -> {
                        tasks.remove(userId, serverResponseTask);
                    });

                    tasks.put(userId, serverResponseTask);
                } else {
                    serverResponseTask = tasks.get(userId);
                }
                if (socket.isConnected()) {
                    executorService.execute(serverResponseTask);
                    System.out.println("connect success!!");
                }
            }
            serverSocket.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (serverSocket != null) {
                try {
                    isStart = false;
                    serverSocket.close();
                    for (ServerResponseTask task : tasks.values()) {
                        task.stop();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

//    public static void main(String[] args) {
//        connect();
//    }
}
